home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Graphics / vpeg / vpeg.c < prev    next >
C/C++ Source or Header  |  2001-06-10  |  21KB  |  568 lines

  1. /*
  2. ** MPEG Hardware Player
  3. **
  4. ** by Sigbjørn (CISC) Skjæret
  5. **
  6. **
  7. ** Do whatever you want with this code, but I'd appreciate it if you contacted
  8. ** me and told me about it first and/or you credited me for it in your project.
  9. **
  10. */
  11.  
  12. #define __USE_SYSBASE
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <proto/dos.h>
  17. #include <proto/exec.h>
  18. #include <exec/memory.h>
  19. #include <exec/execbase.h>
  20. #include <proto/graphics.h>
  21. #include <proto/intuition.h>
  22. #include <proto/peggympeg.h>
  23.  
  24. #include "vpeg.h"
  25.  
  26. #define MAXTOC 100
  27. #define MAXBUF 16384
  28. #define MAXPATH 1024
  29. #define CheckFlag(mask,flag,name) (mask & flag) ? name : ""
  30.  
  31. static const char Version[] = "$VER: VPeg 2.0 (10.06.01)";
  32.  
  33. struct IntuitionBase    *IntuitionBase = NULL;
  34. struct Library            *PeggyMPEGBase;
  35.  
  36. const ULONG  layer[]  = { 0, 3, 2, 1 };
  37. const ULONG  freq[]   = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 };
  38. const STRPTR fps[]    = { "0", "23.976", "24", "25", "29.97", "30", "50", "59.94", "60" };
  39. const STRPTR aspect[] = { "0:0", "1:1", "1:0.6735", "1:0.7031", "1:0.7615", "1:0.8055", "1:0.8437", "1:0.8935", "1:0.9157 (PAL)", "1:0.9815", "1:1.0255", "1:1.0695", "1:1.0950 (NTSC)", "1:1.1575", "1:1.2015" };
  40. const STRPTR mode[]   = { "Stereo", "J-Stereo", "Dual", "Mono" };
  41. const STRPTR track[]  = { "Root", "Data", "Audio", "MPEG", "Whitebook", "Unknown" };
  42.  
  43.  
  44. ULONG IssueRequest(struct IORequest *Request, ULONG WaitSignals)
  45. {
  46.     ULONG signal;
  47.  
  48.     SendIO(Request);
  49.     signal = Wait(WaitSignals);
  50.  
  51.     if (signal & ~(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F))    /* Check if any of the signals are non-break ones */
  52.     {
  53.         while (GetMsg(Request->io_Message.mn_ReplyPort));    /* Empty message-queue */
  54.  
  55.         if (Request->io_Error)    /* Check for error */
  56.         {
  57.             Printf("An error occured while performing command 0x%04lx: %ld.\n", (ULONG)Request->io_Command, (LONG)Request->io_Error);
  58.             return NULL;
  59.         }
  60.     }
  61.  
  62.     return signal;
  63. }
  64.  
  65. ULONG PeggyCtrl(ULONG signal, ULONG usersig, ULONG ctrlsig, ULONG pegdsig, LONG step, struct IOMPEGReq *PeggyIO, struct IOMPEGReq *Peggy2IO)
  66. {
  67.     LONG pause = 0, search = 0;
  68.  
  69.     while (!(signal & usersig))
  70.     {
  71.         if (signal & SIGBREAKF_CTRL_E)
  72.         {
  73.             Peggy2IO->iomr_Req.io_Command = MPEGCMD_PAUSE;
  74.             Peggy2IO->iomr_StreamType     = PeggyIO->iomr_StreamType;
  75.             Peggy2IO->iomr_PauseMode      = (pause ^= 1);
  76.             IssueRequest((struct IORequest *)Peggy2IO, pegdsig);
  77.             search = 0;
  78.         }
  79.  
  80.         if (signal & SIGBREAKF_CTRL_F)
  81.         {
  82.             Peggy2IO->iomr_Req.io_Command = MPEGCMD_SEARCH;
  83.             Peggy2IO->iomr_StreamType     = PeggyIO->iomr_StreamType;
  84.             Peggy2IO->iomr_SearchSpeed    = (search ^= step);
  85.             IssueRequest((struct IORequest *)Peggy2IO, pegdsig);
  86.             pause = 0;
  87.         }
  88.  
  89.         signal = Wait(usersig | ctrlsig);
  90.         while (GetMsg(PeggyIO->iomr_Req.io_Message.mn_ReplyPort));
  91.     }
  92.  
  93.     return signal;
  94. }
  95.  
  96. void PrintStreamInfo(struct MPEGStreamInfo *StreamInfo)
  97. {
  98.     switch (StreamInfo->StreamType)
  99.     {
  100.     case MPEGSTREAM_SYSTEM:
  101.         Printf("System Stream -> %lux%lu %lukbps %sfps %s\n", (ULONG)StreamInfo->Width, (ULONG)StreamInfo->Height, (ULONG)StreamInfo->BitRate/1000, fps[StreamInfo->PictureRate], aspect[StreamInfo->AspectRatio]);
  102.         break;
  103.     case MPEGSTREAM_VIDEO:
  104.         Printf("Video Stream  -> %lux%lu %lukbps %sfps %s\n", (ULONG)StreamInfo->Width, (ULONG)StreamInfo->Height, (ULONG)StreamInfo->BitRate/1000, fps[StreamInfo->PictureRate], aspect[StreamInfo->AspectRatio]);
  105.         break;
  106.     case MPEGSTREAM_AUDIO:
  107.         Printf("Audio Stream  -> Layer%lu %s %luHz %lukbps\n", layer[StreamInfo->AudioLayer], mode[(StreamInfo->AudioMode & MPEGAUD_MODE)>>2], freq[StreamInfo->AudioFreq], (ULONG)StreamInfo->AudioBitRate);
  108.         break;
  109.     default:
  110.         Printf("Unknown streamtype: %lu\n", (ULONG)StreamInfo->StreamType);
  111.         break;
  112.     }
  113. }
  114.  
  115. void ClearMPEGReq(struct IOMPEGReq *PeggyIO)
  116. {
  117.     PeggyIO->iomr_Req.io_Error = 0;
  118.     PeggyIO->iomr_Req.io_Actual = 0;
  119.     PeggyIO->iomr_Req.io_Length = 0;
  120.     PeggyIO->iomr_Req.io_Data = 0;
  121.     PeggyIO->iomr_Req.io_Offset = 0;
  122.  
  123.     PeggyIO->iomr_MPEGError = 0;
  124.     PeggyIO->iomr_Version = 0;
  125.     PeggyIO->iomr_StreamType = 0;
  126.     PeggyIO->iomr_MPEGFlags = 0;
  127.     PeggyIO->iomr_Arg1 = 0;
  128.     PeggyIO->iomr_Arg2 = 0;
  129.     PeggyIO->iomr_PTSHigh = 0;
  130.     PeggyIO->iomr_PTSMid = 0;
  131.     PeggyIO->iomr_PTSLow = 0;
  132. }
  133.  
  134.  
  135. void main(void)
  136. {
  137.     APTR mempool = NULL;
  138.     BYTE PeggyDevice = -1;
  139.     struct RDArgs *rdargs = NULL;
  140.     struct Screen *screen = NULL;
  141.     struct IOMPEGReq *PeggyIO = NULL;
  142.     struct IOMPEGReq *Peggy2IO = NULL;
  143.     struct MsgPort *PeggyMP = NULL;
  144.     struct MsgPort *Peggy2MP = NULL;
  145.     struct PeggyData *Peggy;
  146.  
  147.     STRPTR Template = "FILE/A/M,FINDSYNC/S,NEWSCREEN/S,KEEPSCREEN/S,DISPLAY/K,KEEPAUDIO/S,KEEPVIDEO/S,NOPLAY/S,YCBCRMODE/S,PVC=CONVERTER/S,VOL=VOLUME/N,OP=OPACITY/N,L=LOOPS/N,JL=JUSTIFYLEFT/N,JT=JUSTIFYTOP/N,VCD/S,DEV=DEVICE/K,U=UNIT/N,MPDEV=MPEGDEVICE/K,VERBOSE/S";
  148.     enum { TEM_FILE, TEM_FINDSYNC, TEM_NEWSCREEN, TEM_KEEPSCREEN, TEM_DISPLAY, TEM_KEEPAUDIO, TEM_KEEPVIDEO, TEM_NOPLAY, TEM_YCBCR, TEM_CONVERTER, TEM_VOLUME, TEM_OPACITY, TEM_LOOPS, TEM_JUSTIFYLEFT, TEM_JUSTIFYTOP, TEM_VCD, TEM_DEVICE, TEM_UNIT, TEM_MPEGDEV, TEM_VERBOSE, TEM_NUMARGS };
  149.     LONG ArgArray[TEM_NUMARGS];
  150.     ULONG signal, pegpsig, pegdsig, usersig = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D, ctrlsig = SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F;
  151.  
  152.     STRPTR     tempfile    = "T:vpeg.tmp";
  153.     STRPTR     mpegdev    = "peggympeg.device";
  154.     BPTR     fp            = NULL;
  155.     UWORD     loops        = 1;
  156.     UWORD     converter    = 0;
  157.     UWORD     volume        = 65535;
  158.     UWORD     opacity    = 65535;
  159.     UWORD     justleft    = 0;
  160.     UWORD     justtop    = 0;
  161.     UWORD     picrate    = MPEG_RATE_AUTO;
  162.     ULONG    *filearray;
  163.     STRPTR     filename;
  164.     size_t     bufsize;
  165.     STRPTR     buf;
  166.     unsigned int pos, i, f, x, offset, cdi = 0;
  167.  
  168.     for (i=0;i<TEM_NUMARGS;ArgArray[i++]=NULL);
  169.     if (!(rdargs = ReadArgs(Template,ArgArray,NULL))) { Printf("Invalid arguments.\n"); goto exit; }
  170.     if (ArgArray[TEM_VCD] && (!ArgArray[TEM_DEVICE] || !ArgArray[TEM_UNIT])) { Printf("Missing arguments.\n"); goto exit; }
  171.  
  172.     if (!(mempool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR, sizeof(struct MPEGCDInfo)*MAXTOC*2, sizeof(struct MPEGCDInfo)*MAXTOC))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  173.     if (!(Peggy = AllocPooled(mempool, sizeof(struct PeggyData)))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  174.     if (!(Peggy->DevInfo = AllocPooled(mempool, sizeof(struct MPEGDevInfo)))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  175.     if (!(Peggy->StreamInfo = AllocPooled(mempool, sizeof(struct MPEGStreamInfo)))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  176.     if (!(Peggy->Environment = AllocPooled(mempool, sizeof(struct MPEGEnvironment)))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  177.     if (!(Peggy->AudioParams = AllocPooled(mempool, sizeof(struct MPEGAudioParams)))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  178.     if (!(Peggy->BorderParams = AllocPooled(mempool, sizeof(struct MPEGBorderParams)))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  179.     if (!(Peggy->WindowParams = AllocPooled(mempool, sizeof(struct MPEGWindowParams)))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  180.     if (!(Peggy->VideoParams = AllocPooled(mempool, sizeof(struct MPEGVideoParamsSet)))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  181.  
  182.     if (ArgArray[TEM_LOOPS]) loops = *((ULONG *)ArgArray[TEM_LOOPS]);
  183.     if (ArgArray[TEM_VOLUME]) volume = *((ULONG *)ArgArray[TEM_VOLUME]);
  184.     if (ArgArray[TEM_OPACITY]) opacity = *((ULONG *)ArgArray[TEM_OPACITY]);
  185.     if (ArgArray[TEM_JUSTIFYLEFT]) justleft = *((ULONG *)ArgArray[TEM_JUSTIFYLEFT]);
  186.     if (ArgArray[TEM_JUSTIFYTOP]) justtop = *((ULONG *)ArgArray[TEM_JUSTIFYTOP]);
  187.     if (ArgArray[TEM_MPEGDEV]) mpegdev = (STRPTR)ArgArray[TEM_MPEGDEV];
  188.     if (ArgArray[TEM_CONVERTER]) converter = 1;
  189.     filearray = (ULONG *)ArgArray[TEM_FILE];
  190.  
  191.     if (ArgArray[TEM_DISPLAY])
  192.     {
  193.         if ((x = strlen((STRPTR)ArgArray[TEM_DISPLAY])) > 0)
  194.         {
  195.             if (strnicmp((STRPTR)ArgArray[TEM_DISPLAY], "PAL", x) == 0) picrate = MPEG_RATE_PAL;
  196.             else if (strnicmp((STRPTR)ArgArray[TEM_DISPLAY], "NTSC", x) == 0) picrate = MPEG_RATE_NTSC;
  197.         }
  198.     }
  199.  
  200.     if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37))) { Printf("Unable to open intuition.library v37+.\n"); goto exit; }
  201.  
  202.     if (!(PeggyMP = CreateMsgPort())) { Printf("Unable to create MsgPort.\n"); goto exit; }
  203.     if (!(Peggy2MP = CreateMsgPort())) { Printf("Unable to create MsgPort.\n"); goto exit; }
  204.  
  205.     if (!(PeggyIO = (struct IOMPEGReq *)CreateIORequest(PeggyMP, sizeof(struct IOMPEGReq)))) { Printf("Unable to create IORequest.\n"); goto exit; }
  206.     if (!(Peggy2IO = (struct IOMPEGReq *)AllocMem(sizeof(struct IOMPEGReq), MEMF_PUBLIC))) { Printf("Unable to create IORequest.\n"); goto exit; }
  207.  
  208.     if ((PeggyDevice = OpenDevice(mpegdev, 0, (struct IORequest *)PeggyIO, NULL))) { Printf("Unable to open %s.\n", mpegdev); goto exit; }
  209.     PeggyMPEGBase = (struct Library *)PeggyIO->iomr_Req.io_Device;
  210.  
  211.     CopyMem(PeggyIO, Peggy2IO, sizeof(struct IOMPEGReq));    /* Duplicate PeggyIO */
  212.     Peggy2IO->iomr_Req.io_Message.mn_ReplyPort = Peggy2MP;    /* Set up duplicate PeggyIO with alternate MsgPort */
  213.  
  214.     pegpsig = 1L << PeggyMP->mp_SigBit;
  215.     pegdsig = 1L << Peggy2MP->mp_SigBit;
  216.  
  217.     if (ArgArray[TEM_VERBOSE])
  218.     {
  219.         PeggyIO->iomr_Req.io_Command = MPEGCMD_GETDEVINFO;
  220.         PeggyIO->iomr_Req.io_Data    = Peggy->DevInfo;
  221.         PeggyIO->iomr_Req.io_Length  = sizeof(struct MPEGDevInfo);
  222.         if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  223.  
  224.         Printf("Board:         %s\n",Peggy->DevInfo->mdi_BoardDesc);
  225.         Printf("Version:       %lu\n",(ULONG)Peggy->DevInfo->mdi_Version);
  226.         Printf("Capabilities: %s%s%s%s%s%s%s%s%s\n\n",
  227.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_PLAYRAWVIDEO," RawVideo"),
  228.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_PLAYRAWAUDIO," RawAudio"),
  229.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_PLAYSYSTEM," System"),
  230.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_WINDOWVIDEO," Window"),
  231.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_SCALEVIDEO," Scale"),
  232.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_STEPPLAY," Step"),
  233.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_SCANPLAY," Scan"),
  234.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_SLOWPLAY," Slow"),
  235.             CheckFlag(Peggy->DevInfo->mdi_BoardCapabilities,MPEGCF_READFRAME," Read"));
  236.     }
  237.  
  238.     if (ArgArray[TEM_NEWSCREEN])
  239.     {
  240.         ULONG display;
  241.  
  242.         switch (picrate)
  243.         {
  244.         case MPEG_RATE_NTSC:
  245.             display = NTSC_MONITOR_ID;
  246.             break;
  247.         case MPEG_RATE_PAL:
  248.             display = PAL_MONITOR_ID;
  249.             break;
  250.         default:
  251.             if (SysBase->ex_EClockFrequency==715909) display = NTSC_MONITOR_ID;
  252.             else display = PAL_MONITOR_ID;
  253.             break;
  254.         }
  255.         screen = OpenScreenTags(NULL, SA_DisplayID, display, SA_ShowTitle, FALSE, SA_Draggable, FALSE, TAG_END);
  256.  
  257.         if (!ArgArray[TEM_KEEPSCREEN])
  258.         {
  259.             CloseScreen(screen);
  260.             screen = NULL;
  261.  
  262.             CloseLibrary((struct Library *)IntuitionBase);
  263.             IntuitionBase = NULL;
  264.         }
  265.     }
  266.  
  267.     if (ArgArray[TEM_FINDSYNC])
  268.     {
  269.         if (!(buf = (STRPTR)AllocPooled(mempool, MAXBUF))) { Printf("Unable to allocate needed memory.\n"); goto exit; }
  270.     }
  271.  
  272.  
  273. //    /* Init the Peggy+ board */
  274. //    PeggyIO->iomr_Req.io_Message.mn_Node.ln_Pri = 0;
  275. //    PeggyIO->iomr_Req.io_Command = CMD_RESET;
  276. //    if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  277.  
  278.     /* Video init */
  279.     Peggy->VideoParams->mvp_Fade        = opacity;        /* No effect on Peggy+ (except no video when 0) */
  280.     Peggy->VideoParams->mvp_VideoOutput = converter;
  281.     Peggy->VideoParams->mvp_DisplayType    = picrate;
  282.     if (ArgArray[TEM_YCBCR]) Peggy->VideoParams->mvp_ColorMode   = YCbCr_MODE;
  283.     else                     Peggy->VideoParams->mvp_ColorMode   = RGB_MODE;
  284.  
  285.     PeggyIO->iomr_Req.io_Command = MPEGCMD_SETVIDEOPARAMS;
  286.     PeggyIO->iomr_Req.io_Data    = Peggy->VideoParams;
  287.     PeggyIO->iomr_Req.io_Length  = sizeof(struct MPEGVideoParamsSet);
  288.     if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  289.  
  290.     /* Audio init */
  291.     Peggy->AudioParams->map_VolumeLeft  = volume;        /* No effect on Peggy+ (except no audio when 0) */
  292.     Peggy->AudioParams->map_VolumeRight = volume;
  293.     Peggy->AudioParams->map_AudioMode   = MPEG_AUDIO;
  294. //    Peggy->AudioParams->map_StreamID    = ~0;            /* WTF is this for? */
  295.  
  296.     PeggyIO->iomr_Req.io_Command = MPEGCMD_SETAUDIOPARAMS;
  297.     PeggyIO->iomr_Req.io_Data    = Peggy->AudioParams;
  298.     PeggyIO->iomr_Req.io_Length  = sizeof(struct MPEGAudioParams);
  299.     if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  300.  
  301.     /* Border init */
  302.     Peggy->BorderParams->mbp_BorderLeft = justleft;
  303.     Peggy->BorderParams->mbp_BorderTop  = justtop;
  304.  
  305.     PeggyIO->iomr_Req.io_Command = MPEGCMD_SETBORDER;
  306.     PeggyIO->iomr_Req.io_Data    = Peggy->BorderParams;
  307.     PeggyIO->iomr_Req.io_Length  = sizeof(struct MPEGBorderParams);
  308.     if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  309.  
  310. //    if (ArgArray[TEM_CROP])
  311. //    {
  312. //        Peggy->WindowParams->mwp_XOffset = 0;
  313. //        Peggy->WindowParams->mwp_YOffset = 0;
  314. //        Peggy->WindowParams->mwp_Width   = 704;    /* 352 low-res pixels */
  315. //        Peggy->WindowParams->mwp_Height  = 288;    /* This is Peggy+ max */
  316.  
  317. //        PeggyIO->iomr_Req.io_Command = MPEGCMD_SETWINDOW;
  318. //        PeggyIO->iomr_Req.io_Data    = Peggy->WindowParams;
  319. //        PeggyIO->iomr_Req.io_Length  = sizeof(struct MPEGWindowParams);
  320. //        if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  321. //    }
  322.  
  323.  
  324.     if (ArgArray[TEM_VCD])
  325.     {
  326.         if (!(Peggy->CDInfo = AllocPooled(mempool, sizeof(struct MPEGCDInfo)*MAXTOC))) { Printf("Unable to allocate needed memory.\n"); goto end; }
  327.  
  328.         Peggy->Environment->met_Length  = sizeof(struct MPEGEnvironment);
  329.         Peggy->Environment->met_Device  = (STRPTR)ArgArray[TEM_DEVICE];
  330.         Peggy->Environment->met_DevUnit = *((ULONG *)ArgArray[TEM_UNIT]);
  331.         Peggy->Environment->met_DevType = MPEGDEV_CDXA;
  332.  
  333.         PeggyIO->iomr_Req.io_Command = MPEGCMD_GETCDCONTENTS;
  334.         PeggyIO->iomr_Req.io_Data    = Peggy->CDInfo;
  335.         PeggyIO->iomr_Req.io_Length  = sizeof(struct MPEGCDInfo)*MAXTOC;
  336.         PeggyIO->iomr_Arg1           = (LONG)Peggy->Environment;
  337.         if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  338.  
  339.         if (ArgArray[TEM_VERBOSE])
  340.         {
  341.             Printf("Title:   %s\n", Peggy->CDInfo[0].mcd_Name);
  342.             Printf("Blocks:  %lu\n\n", Peggy->CDInfo[0].mcd_Length);
  343.         }
  344.  
  345.         if (Peggy->CDInfo[0].mcd_Length)
  346.         for (i=1;Peggy->CDInfo[i].mcd_Length;i++)
  347.         {
  348.             if (ArgArray[TEM_VERBOSE])
  349.             {
  350.                 Printf("Track %lu: %s\n", (ULONG)Peggy->CDInfo[i].mcd_TrackNumber, Peggy->CDInfo[i].mcd_Name);
  351.                 Printf("Blocks:  %lu-%lu\n", Peggy->CDInfo[i].mcd_StartBlock, Peggy->CDInfo[i].mcd_StartBlock + Peggy->CDInfo[i].mcd_Length);
  352.             }
  353.  
  354.             if (Peggy->CDInfo[i].mcd_Length == Peggy->CDInfo[0].mcd_Length)
  355.             {
  356.                 if (!GetCDStreamInfo(Peggy->Environment, Peggy->StreamInfo, 4250, sizeof(struct MPEGStreamInfo)))
  357.                 {
  358.                     UWORD Width = Peggy->StreamInfo->Width, Height = Peggy->StreamInfo->Height;
  359.                     ULONG BitRate = Peggy->StreamInfo->BitRate;
  360.  
  361.                     cdi = 4250;
  362.                     if (ArgArray[TEM_VERBOSE]) Printf("Possible CDi detected, checking for bumper-sequence...\n");
  363.  
  364.                     for (f=5300;f<6000;f++)
  365.                     {
  366.                         GetCDStreamInfo(Peggy->Environment, Peggy->StreamInfo, f, sizeof(struct MPEGStreamInfo));
  367.  
  368.                         if (Peggy->StreamInfo->StreamType == MPEGSTREAM_SYSTEM && Peggy->StreamInfo->Height != 0 && (Peggy->StreamInfo->Height != Height || Peggy->StreamInfo->Width != Width || Peggy->StreamInfo->BitRate != BitRate))
  369.                         {
  370.                             cdi = f;
  371.                             if (ArgArray[TEM_VERBOSE]) Printf("Bumper-sequence detected, skipping to sector %lu!\n", cdi);
  372.                             break;
  373.                         }
  374.                     }
  375.  
  376.                     Peggy->CDInfo[i].mcd_TrackType = TRACKTYPE_WHITEMPEG;
  377.                     Peggy->CDInfo[i].mcd_StartBlock = cdi;
  378.                     Peggy->CDInfo[i].mcd_Length -= cdi;
  379.                 }
  380.             }
  381.  
  382.             if (Peggy->CDInfo[i].mcd_TrackType == TRACKTYPE_MPEG || Peggy->CDInfo[i].mcd_TrackType == TRACKTYPE_WHITEMPEG)
  383.             {
  384.                 x = GetCDStreamInfo(Peggy->Environment, Peggy->StreamInfo, Peggy->CDInfo[i].mcd_StartBlock, sizeof(struct MPEGStreamInfo));
  385.  
  386.                 if (!x)
  387.                 {
  388.                     if (ArgArray[TEM_VERBOSE]) PrintStreamInfo(Peggy->StreamInfo);
  389.                 }
  390.                 else { if (!cdi) Printf("Couldn't figure out filetype of track %lu.\n", i); continue; }
  391.  
  392.                 if (!ArgArray[TEM_NOPLAY])
  393.                 {
  394.                     ClearMPEGReq(PeggyIO);
  395.  
  396.                     PeggyIO->iomr_Req.io_Command = MPEGCMD_PLAYLSN;
  397.                     PeggyIO->iomr_Req.io_Data    = Peggy->Environment;
  398.                     PeggyIO->iomr_Req.io_Offset  = Peggy->CDInfo[i].mcd_StartBlock;
  399.                     PeggyIO->iomr_Req.io_Length  = Peggy->CDInfo[i].mcd_Length;
  400.                     PeggyIO->iomr_StreamType     = Peggy->StreamInfo->StreamType;
  401.                     PeggyIO->iomr_SectorSize     = 2328;    /* The data is really just 2324 */
  402.                     PeggyIO->iomr_StreamStart    = Peggy->CDInfo[i].mcd_StartBlock;
  403.  
  404.                     if (loops != 1)
  405.                     {
  406.                         PeggyIO->iomr_MPEGFlags  = MPEGF_REPEAT;
  407.                         PeggyIO->iomr_Loops      = loops;
  408.                     }
  409.  
  410.                     if (ArgArray[TEM_VERBOSE]) Printf("Playing %s track (CTRL-D to skip / CTRL-C to exit).\n\n", track[Peggy->CDInfo[i].mcd_TrackType]);
  411.                     if (!(signal = IssueRequest((struct IORequest *)PeggyIO, pegpsig | usersig | ctrlsig))) goto exit;
  412.  
  413.                     if (signal & ctrlsig)
  414.                     {
  415.                         signal = PeggyCtrl(signal, pegpsig | usersig, ctrlsig, pegdsig, 100, PeggyIO, Peggy2IO);
  416.                     }
  417.  
  418.                     if (signal & usersig)
  419.                     {
  420.                         AbortIO((struct IORequest *)PeggyIO);
  421.                         WaitIO((struct IORequest *)PeggyIO);
  422.                         SetSignal(0L, pegpsig | usersig);    /* Clear signalbits since WaitIO most likely preserves them */
  423.  
  424.                         if (signal & SIGBREAKF_CTRL_C) break;
  425.                         if (signal & SIGBREAKF_CTRL_D) continue;
  426.                     }
  427.                 }
  428.             }
  429.         }
  430.     }
  431.     else
  432.     {
  433.         if (!(Peggy->WildAnchor = AllocPooled(mempool, sizeof(struct AnchorPath) + MAXPATH))) { Printf("Unable to allocate needed memory.\n"); goto end; }
  434.         Peggy->WildAnchor->ap_Strlen = MAXPATH;
  435.  
  436.         for (f=0,x=0,offset=0;filearray[f];f++)
  437.         {
  438.             if (!MatchFirst((STRPTR)filearray[f], Peggy->WildAnchor))
  439.             {
  440.                 do
  441.                 {
  442.                     filename = Peggy->WildAnchor->ap_Buf;
  443.  
  444.                     if (ArgArray[TEM_FINDSYNC])
  445.                     {
  446.                         if (!(fp = Open(filename, MODE_OLDFILE))) { Printf("Couldn't open \"%s\".\n", filename); continue; }
  447.  
  448.                         for (pos=0;(bufsize=Read(fp, buf, MAXBUF))>0;pos+=bufsize)
  449.                         {
  450.                             for (i=0;i<bufsize-4;i++)    /* We're lazy, don't overlap buffers */
  451.                             {
  452.                                 if (buf[i]==0x00 && buf[i+1]==0x00 && buf[i+2]==0x01 && (buf[i+3]==0xBA || buf[i+3]==0xB3))
  453.                                 {
  454.                                     offset = pos+i;
  455.                                     x = 1;
  456.                                     break;
  457.                                 }
  458.                             }
  459.                             if (x) break;
  460.  
  461.                             if (SetSignal(0,0) & SIGBREAKF_CTRL_C) { MatchEnd(Peggy->WildAnchor); goto end; }
  462.                         }
  463.  
  464.                         Close(fp);
  465.                         fp = NULL;
  466.                     }
  467.  
  468.                     if (ArgArray[TEM_FINDSYNC] && x)
  469.                     {
  470.                         if (ArgArray[TEM_VERBOSE]) Printf("Found sync at %lu\n", offset);
  471.  
  472.                         if ((fp = Open(tempfile, MODE_NEWFILE)))
  473.                         {
  474.                             Write(fp, &buf[i], bufsize-i);
  475.                             Close(fp);
  476.                             fp = NULL;
  477.  
  478.                             x = GetStreamInfo(tempfile, Peggy->StreamInfo, sizeof(struct MPEGStreamInfo));
  479.                             DeleteFile(tempfile);
  480.                         }
  481.                     }
  482.                     else x = GetStreamInfo(filename, Peggy->StreamInfo, sizeof(struct MPEGStreamInfo));
  483.  
  484.                     if (!x)
  485.                     {
  486.                         if (ArgArray[TEM_VERBOSE]) PrintStreamInfo(Peggy->StreamInfo);
  487.                     }
  488.                     else { Printf("Couldn't figure out filetype of, or unable to open \"%s\".\n", filename); continue; }
  489.  
  490.                     if (!ArgArray[TEM_NOPLAY])
  491.                     {
  492.                         ClearMPEGReq(PeggyIO);
  493.  
  494.                         PeggyIO->iomr_Req.io_Command = MPEGCMD_PLAYFILE;
  495.                         PeggyIO->iomr_Req.io_Data    = filename;
  496.                         PeggyIO->iomr_Req.io_Offset  = offset;
  497.                         PeggyIO->iomr_Req.io_Length  = strlen(filename);
  498.                         PeggyIO->iomr_StreamType     = Peggy->StreamInfo->StreamType;
  499.  
  500.                         if (loops != 1)
  501.                         {
  502.                             PeggyIO->iomr_MPEGFlags  = MPEGF_REPEAT;
  503.                             PeggyIO->iomr_Loops      = loops;
  504.                         }
  505.  
  506.                         if (ArgArray[TEM_VERBOSE]) Printf("Playing \"%s\" (CTRL-D to skip / CTRL-C to exit).\n\n", filename);
  507.                         if (!(signal = IssueRequest((struct IORequest *)PeggyIO, pegpsig | usersig | ctrlsig))) { MatchEnd(Peggy->WildAnchor); goto exit; }
  508.  
  509.                         if (signal & ctrlsig)
  510.                         {
  511.                             signal = PeggyCtrl(signal, pegpsig | usersig, ctrlsig, pegdsig, 1, PeggyIO, Peggy2IO);
  512.                         }
  513.  
  514.                         if (signal & usersig)
  515.                         {
  516.                             AbortIO((struct IORequest *)PeggyIO);
  517.                             WaitIO((struct IORequest *)PeggyIO);
  518.                             SetSignal(0L, pegpsig | usersig);    /* Clear signalbits since WaitIO most likely preserves them */
  519.  
  520.                             if (signal & SIGBREAKF_CTRL_C) { MatchEnd(Peggy->WildAnchor); goto end; }
  521.                             if (signal & SIGBREAKF_CTRL_D) continue;
  522.                         }
  523.                     }
  524.                 } while (!MatchNext(Peggy->WildAnchor));
  525.  
  526.                 MatchEnd(Peggy->WildAnchor);
  527.             }
  528.         }
  529.     }
  530.  
  531. end:
  532.     ClearMPEGReq(PeggyIO);
  533.  
  534.     if (!ArgArray[TEM_KEEPAUDIO])
  535.     {
  536.         Peggy->AudioParams->map_AudioMode = AMIGA_AUDIO;
  537.  
  538.         PeggyIO->iomr_Req.io_Command = MPEGCMD_SETAUDIOPARAMS;
  539.         PeggyIO->iomr_Req.io_Data    = Peggy->AudioParams;
  540.         PeggyIO->iomr_Req.io_Length  = sizeof(struct MPEGAudioParams);
  541.         if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  542.     }
  543.  
  544.     if (!ArgArray[TEM_KEEPVIDEO])
  545.     {
  546.         Peggy->VideoParams->mvp_Fade = 0;
  547.  
  548.         PeggyIO->iomr_Req.io_Command = MPEGCMD_SETVIDEOPARAMS;
  549.         PeggyIO->iomr_Req.io_Data    = Peggy->VideoParams;
  550.         PeggyIO->iomr_Req.io_Length  = sizeof(struct MPEGVideoParamsSet);
  551.         if (!IssueRequest((struct IORequest *)PeggyIO, pegpsig)) goto exit;
  552.     }
  553.  
  554. exit:
  555.     if (fp)                Close(fp);
  556.     if (rdargs)            FreeArgs(rdargs);
  557.     if (screen)            CloseScreen(screen);
  558.  
  559.     if (!PeggyDevice)    CloseDevice((struct IORequest *)PeggyIO);
  560.     if (PeggyIO)        DeleteIORequest((struct IORequest *)PeggyIO);
  561.     if (Peggy2IO)        DeleteIORequest((struct IORequest *)Peggy2IO);
  562.     if (PeggyMP)        DeleteMsgPort(PeggyMP);
  563.     if (Peggy2MP)        DeleteMsgPort(Peggy2MP);
  564.  
  565.     if (mempool)        DeletePool(mempool);
  566.     if (IntuitionBase)    CloseLibrary((struct Library *)IntuitionBase);
  567. }
  568.